<?php
if (!defined('IS_INITPHP')) exit('Access Denied!');
/*********************************************************************************
 * InitPHP 3.8.1 国产PHP开发框架   Dao-mysqli 基类
 *-------------------------------------------------------------------------------
 * 版权所有: CopyRight By initphp.com
 * 您可以自由使用该源码，但是在使用过程中，请保留作者信息。尊重他人劳动成果就是尊重自己
 *-------------------------------------------------------------------------------
 * $Author:zhuli
 * $Dtime:2013-5-29 
***********************************************************************************/
class pdoInit extends dbbaseInit{
	public static $pool_id=0;
	public $dbh; //PDO对象
	public $sth;
	public $link_id=0; //链接对象 
	/* !CodeTemplates.overridecomment.nonjd!
	 * @see dbbaseInit::connect()
	 */
	public function connect($host, $user, $password, $database, $charset = 'utf8', $pconnect = 0) {
		$this->link_id=self::$pool_id++;
		// TODO 自动生成的方法存根
		$dsn="mysql:host=$host; port=3306; dbname=$database";
		$this->dbh[$this->link_id]=new PDO($dsn,
                    $user,
                    $password,
                    array(
                        PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC,
                        PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,
                    ));
		$this->dbh=new PDO($dsn,
                    $user,
                    $password,
                    array(
                        PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC,
                        PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,
                    ));
// 		$this->dbh->setAttribute($attribute, $value)
		$this->dbh[$this->link_id]->exec("SET NAMES {$charset}");
		return $this->link_id;
	}

	/* !CodeTemplates.overridecomment.nonjd!
	 * @see dbbaseInit::query()
	 */
	public function query($sql) {
		// TODO 自动生成的方法存根
// 		$this->dbh->query($statement)
		$this->sth=$this->_preExec($this->dbh[$this->link_id], $sql, null);
		return $this->dbh[$this->link_id]->query($sql);
	}

	/* !CodeTemplates.overridecomment.nonjd!
	 * @see dbbaseInit::result()
	 */
	public function result($result, $num = 1) {
		// TODO 自动生成的方法存根
	}

	/* !CodeTemplates.overridecomment.nonjd!
	 * @see dbbaseInit::fetch_assoc()
	 */
	public function fetch_assoc($result) {
		// TODO 自动生成的方法存根
		
	}

	/* !CodeTemplates.overridecomment.nonjd!
	 * @see dbbaseInit::fetch_fields()
	 */
	public function fetch_fields($result) {
		// TODO 自动生成的方法存根
		
	}

	/* !CodeTemplates.overridecomment.nonjd!
	 * @see dbbaseInit::affected_rows()
	 */
	public function affected_rows() {
		// TODO 自动生成的方法存根
		return $sth->rowCount();
	}

	/* !CodeTemplates.overridecomment.nonjd!
	 * @see dbbaseInit::num_rows()
	 */
	public function num_rows($result) {
		// TODO 自动生成的方法存根
		
	}

	/* !CodeTemplates.overridecomment.nonjd!
	 * @see dbbaseInit::num_fields()
	 */
	public function num_fields($result) {
		// TODO 自动生成的方法存根
		
	}

	/* !CodeTemplates.overridecomment.nonjd!
	 * @see dbbaseInit::insert_id()
	 */
	public function insert_id() {
		// TODO 自动生成的方法存根
		
	}

	/* !CodeTemplates.overridecomment.nonjd!
	 * @see dbbaseInit::free_result()
	 */
	public function free_result($result) {
		// TODO 自动生成的方法存根
		
	}

	/* !CodeTemplates.overridecomment.nonjd!
	 * @see dbbaseInit::close()
	 */
	public function close() {
		// TODO 自动生成的方法存根
		
	}

	/* !CodeTemplates.overridecomment.nonjd!
	 * @see dbbaseInit::error()
	 */
	public function error() {
		// TODO 自动生成的方法存根
		
	}
	/**
	 * @param PDO $pdo
	 * @param string $sql
	 * @param array $params
	 * @throws Exception
	 * @return PDOStatement
	 */
	private  function _preExec($pdo, $sql, $params) {
		//writeLog('sql:'.$sql.'||params:'.$params,'sql_log');
		try {
			$sth = $pdo->prepare($sql);
			$sth->execute($params);
		} catch (Exception $e) {
			$error_info = $e->errorInfo;
			$data['error_code'] = $error_info[1];
			$data['error'] = $error_info[2];
			if ($data['error_code'] == 2006) {
				$error_log = date("Y年n月d日  H:i:s", time()) . ':' . $e->__toString() . '||sql:' . $sql . '||data:' . print_r($params,true);
				writeLog($error_log, 'sql_gone_away_error');
				$this->close();
				$master_slave = key($this->configs);
	
				$pdo = $this->getPdo($master_slave);
				return $this->_preExec($pdo, $sql, $params);
			}
			$error_log = $e->__toString() . '||sql:' . $sql . '||data:' . print_r($params,true);
	
			$this->logError($error_log,$data['error_code']);
			return $data;
		}
		return $sth;
	}
	/**
	 * 对sql语句进行预处理，同时对参数进行同步处理 ,以实现在调用时sql和参数多种占位符格式支持
	 * 如 $where="id=1" , $params=1 处理成$where="id=:id",$params['id']=1
	 * @param string $where
	 * @param array $params
	 */
	public function _paramParse(&$where, &$params) {
		if (is_null($params)) {
			$params = array();
			return;
		};
	
		if (!is_array($params))
			$params = array($params);
		$_first = each($params);
		$tmp = array();
		if (!is_int($_first['key'])) {
			foreach ($params as $_k => $_v) {
				$tmp[":" . ltrim($_k, ":")] = $_v;
			}
		} else {
			preg_match_all("/`?([\w_]+)`?\s*[\=<>!]+\s*\?\s+/i", $where . " ", $matches, PREG_SET_ORDER);
			if ($matches) {
				foreach ($matches as $_k => $matche) {
					$fieldName = ":" . $matche[1]; //字段名称
					$i = 0;
					while (array_key_exists($fieldName, $params)) {
						$fieldName = ":" . $matche[1] . "_" . ($i++);
					}
					$where = str_replace(trim($matche[0]), str_replace("?", $fieldName, $matche[0]), $where);
					if (array_key_exists($_k, $params)) {
						$tmp[$fieldName] = $params[$_k];
					}
				}
			}
		}
		$params = $tmp;
	
		//------------------------------------------
		//fix sql like: select * from table_name where id in(:ids)
		preg_match_all("/\s+in\s*\(\s*(\:\w+)\s*\)/i", $where . " ", $matches, PREG_SET_ORDER);
	
		if ($matches) {
			foreach ($matches as $_k => $matche) {
	
				$fieldName = trim($matche[1], ":");
	
				$_val = $params[$matche[1]];
	
				if (!is_array($_val)) {
					$_val = explode(",", addslashes($_val));
				}
	
				$_tmpStrArray = array();
				foreach ($_val as $_item) {
					$_tmpStrArray[] = is_numeric($_item) ? $_item : "'" . $_item . "'";
				}
				$_val = implode(",", $_tmpStrArray);
				$where = str_replace($matche[0], " In (" . $_val . ") ", $where);
	
				unset($params[$matche[1]]);
			}
		}
		//==========================================
	}
	
}
